package edu.se.jai.lesson01.ws;

import edu.se.jai.lesson01.config.FeatureConfig;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;

import java.io.IOException;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * WebSocket Echo处理器
 * 
 * 功能说明：
 * 1. 处理WebSocket连接的生命周期
 * 2. 实现消息的收发和回显
 * 3. 支持心跳检测（ping/pong）
 * 4. 提供扩展功能的基础框架
 * 
 * 扩展功能框架：
 * - 会话管理：维护在线连接集合
 * - 速率限制：防止消息洪水攻击
 * - 空闲检测：及时清理僵尸连接
 * - 广播功能：支持一对多消息分发
 * - 指标统计：收集连接和消息数据
 *
 */
public class EchoWebSocketHandler extends TextWebSocketHandler {
    
    /** 日志记录器 */
    private static final Logger log = LoggerFactory.getLogger(EchoWebSocketHandler.class);

    /** 全局config */
    private final FeatureConfig featureConfig;

    /*所有连接Session集合*/
    private static final Set<WebSocketSession> SESSIONS = ConcurrentHashMap.newKeySet();


    public EchoWebSocketHandler(FeatureConfig featureConfig) {
        this.featureConfig = featureConfig;
    }

    /**
     * 连接建立后的处理
     * 
     * 实现说明：
     * 1. 记录连接建立日志
     * 2. 将会话添加到管理集合（扩展功能）
     * 3. 初始化会话相关数据
     * 
     * @param session WebSocket会话
     * @throws Exception 处理异常
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        log.info("[open] {}", session.getId());
        //添加session到集合
        SESSIONS.add(session);
    }

    /**
     * 处理文本消息
     * 
     * 实现说明：
     * 1. 消息大小限制检查（防止恶意大消息）
     * 2. 速率限制检查（防止消息洪水）
     * 3. 心跳消息处理（ping/pong）
     * 4. 广播消息处理（一对多分发）
     * 5. 普通消息回显
     * 
     * 安全防护：
     * - 消息大小限制：超过1KB自动关闭连接
     * - 速率限制：每秒最多5条消息
     * - 输入验证：防止恶意内容
     * 
     * @param session WebSocket会话
     * @param message 接收到的文本消息
     * @throws IOException 消息处理异常
     */
    @Override
    protected void handleTextMessage(WebSocketSession session, TextMessage message) throws IOException {
        String payload = message.getPayload();

        // 其他处理逻辑...
        log.info("[message] {} -> {}", session.getId(), payload);

        // 心跳消息处理
        if ("ping".equalsIgnoreCase(payload)) {
            session.sendMessage(new TextMessage("pong"));
            return;
        }
        session.sendMessage(new TextMessage(payload));
    }


    /**
     * 连接关闭后的处理
     * 
     * 实现说明：
     * 1. 记录连接关闭日志
     * 2. 清理会话相关数据
     * 3. 更新连接统计信息
     * 
     * @param session WebSocket会话
     * @param status 关闭状态
     * @throws Exception 处理异常
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        log.info("[close] {} code={}, reason={}", session.getId(), status.getCode(), status.getReason());
        //删除session
        SESSIONS.remove(session);
    }

    /**
     * 处理传输错误
     *
     * 实现说明：
     * 1. 记录错误日志
     * 2. 清理相关资源
     * 3. 错误恢复处理
     *
     * @param session WebSocket会话
     * @param exception 传输异常
     * @throws Exception 处理异常
     */
    @Override
    public void handleTransportError(WebSocketSession session, Throwable exception) throws Exception {
        log.warn("[error] {} -> {}", session != null ? session.getId() : "-", exception.getMessage());
    }
}


